X11: Support keyboard-initiated move and resize operations
authorMatthias Clasen <mclasen@redhat.com>
Mon, 13 Jan 2014 03:06:59 +0000 (22:06 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Mon, 13 Jan 2014 03:25:19 +0000 (22:25 -0500)
The EWMH defines _NET_WM_MOVERESIZE_SIZE_KEYBOARD and
_NET_WM_MOVERESIZE_MOVE_KEYBOARD for operations that are not
initiated by a button-press event. Allow using these by passing
a button of 0 to gdk_window_begin_move/resize_drag.

gdk/gdkwindow.c
gdk/x11/gdkwindow-x11.c

index 0f59c56f246eecb51c90b95d18efa90d9d626b2e..e613d9bbd846c672564785a6f8d261500853001d 100644 (file)
@@ -10205,7 +10205,7 @@ gdk_window_set_functions (GdkWindow    *window,
  * @window: a toplevel #GdkWindow
  * @edge: the edge or corner from which the drag is started
  * @device: the device used for the operation
- * @button: the button being used to drag
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
  * @root_x: root window X coordinate of mouse click that began the drag
  * @root_y: root window Y coordinate of mouse click that began the drag
  * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
@@ -10234,7 +10234,7 @@ gdk_window_begin_resize_drag_for_device (GdkWindow     *window,
  * gdk_window_begin_resize_drag:
  * @window: a toplevel #GdkWindow
  * @edge: the edge or corner from which the drag is started
- * @button: the button being used to drag
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
  * @root_x: root window X coordinate of mouse click that began the drag
  * @root_y: root window Y coordinate of mouse click that began the drag
  * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
@@ -10266,7 +10266,7 @@ gdk_window_begin_resize_drag (GdkWindow     *window,
  * gdk_window_begin_move_drag_for_device:
  * @window: a toplevel #GdkWindow
  * @device: the device used for the operation
- * @button: the button being used to drag
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
  * @root_x: root window X coordinate of mouse click that began the drag
  * @root_y: root window Y coordinate of mouse click that began the drag
  * @timestamp: timestamp of mouse click that began the drag
@@ -10295,7 +10295,7 @@ gdk_window_begin_move_drag_for_device (GdkWindow *window,
 /**
  * gdk_window_begin_move_drag:
  * @window: a toplevel #GdkWindow
- * @button: the button being used to drag
+ * @button: the button being used to drag, or 0 for a keyboard-initiated drag
  * @root_x: root window X coordinate of mouse click that began the drag
  * @root_y: root window Y coordinate of mouse click that began the drag
  * @timestamp: timestamp of mouse click that began the drag
index 186b8dfdb57f36ee6f426191e64888a6fc59ec64..22252768fcb8c100a99197081230004200095d4f 100644 (file)
@@ -4760,8 +4760,8 @@ wmspec_moveresize (GdkWindow *window,
 {
   GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
 
-  /* Release passive grab */
-  gdk_device_ungrab (device, timestamp);
+  if (button != 0)
+    gdk_device_ungrab (device, timestamp); /* Release passive grab */
   GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
 
   wmspec_send_message (display, window, root_x, root_y, direction, button);
@@ -4778,48 +4778,51 @@ wmspec_resize_drag (GdkWindow     *window,
 {
   gint direction;
   
-  /* Let the compiler turn a switch into a table, instead
-   * of doing the table manually, this way is easier to verify.
-   */
-  switch (edge)
-    {
-    case GDK_WINDOW_EDGE_NORTH_WEST:
-      direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
-      break;
+  if (button == 0)
+    direction = _NET_WM_MOVERESIZE_SIZE_KEYBOARD;
+  else
+    switch (edge)
+      {
+      /* Let the compiler turn a switch into a table, instead
+       * of doing the table manually, this way is easier to verify.
+       */
+      case GDK_WINDOW_EDGE_NORTH_WEST:
+        direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
+        break;
 
-    case GDK_WINDOW_EDGE_NORTH:
-      direction = _NET_WM_MOVERESIZE_SIZE_TOP;
-      break;
+      case GDK_WINDOW_EDGE_NORTH:
+        direction = _NET_WM_MOVERESIZE_SIZE_TOP;
+        break;
 
-    case GDK_WINDOW_EDGE_NORTH_EAST:
-      direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
-      break;
+      case GDK_WINDOW_EDGE_NORTH_EAST:
+        direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
+        break;
 
-    case GDK_WINDOW_EDGE_WEST:
-      direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
-      break;
+      case GDK_WINDOW_EDGE_WEST:
+        direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
+        break;
 
-    case GDK_WINDOW_EDGE_EAST:
-      direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
-      break;
+      case GDK_WINDOW_EDGE_EAST:
+        direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
+        break;
 
-    case GDK_WINDOW_EDGE_SOUTH_WEST:
-      direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
-      break;
+      case GDK_WINDOW_EDGE_SOUTH_WEST:
+        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
+        break;
 
-    case GDK_WINDOW_EDGE_SOUTH:
-      direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
-      break;
+      case GDK_WINDOW_EDGE_SOUTH:
+        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
+        break;
 
-    case GDK_WINDOW_EDGE_SOUTH_EAST:
-      direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
-      break;
+      case GDK_WINDOW_EDGE_SOUTH_EAST:
+        direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
+        break;
 
-    default:
-      g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
-                 edge);
-      return;
-    }
+      default:
+        g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
+                   edge);
+        return;
+      }
   
   wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
 }
@@ -5036,7 +5039,8 @@ _gdk_x11_moveresize_handle_event (XEvent *event)
 
   impl = GDK_WINDOW_IMPL_X11 (mv_resize->moveresize_window->impl);
 
-  button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
+  if (mv_resize->moveresize_button != 0)
+    button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
 
   switch (event->xany.type)
     {
@@ -5330,14 +5334,19 @@ gdk_x11_window_begin_move_drag (GdkWindow *window,
                                gint       root_y,
                                guint32    timestamp)
 {
-  if (GDK_WINDOW_DESTROYED (window) ||
-      !WINDOW_IS_TOPLEVEL (window))
+  gint direction;
+
+  if (GDK_WINDOW_DESTROYED (window) || !WINDOW_IS_TOPLEVEL (window))
     return;
 
+  if (button == 0)
+    direction = _NET_WM_MOVERESIZE_MOVE_KEYBOARD;
+  else
+    direction = _NET_WM_MOVERESIZE_MOVE;
+
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
                                           gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
-    wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
-                       device, button, root_x, root_y, timestamp);
+    wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
   else
     emulate_move_drag (window, device, button, root_x, root_y, timestamp);
 }